/*
 *  Copyright (C) 2009  Peter Kist & Jan Ripke
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include <boost/test/unit_test.hpp>
#include <boost/make_shared.hpp>
//#include <boost/shared_ptr.hpp>
//#include <boost/weak_ptr.hpp>

//#include <vector>

#include <world/PropertyFactory.h>
//#include <world/Property.h>
#include <world/BehaviorFactory.h>
//#include <world/Behavior.h>
#include <world/Entity.h>
#include <world/Universe.h>

using namespace galaxy::world;
using namespace std;

BOOST_AUTO_TEST_SUITE( test_suite_world )

//--------------------------------------------------------
//  PROPERTY TEST
//--------------------------------------------------------

#define TEST_PROPERTY_POSITION "test.property.position"

struct TestProperty : public Property {
public:
    
    static Property::Type c_TestType;

	int x,y,z;
	TestProperty () { x = 0; y = 0; z = 0; };
    TestProperty(TestProperty& p) : x(p.x), y(p.y), z(p.z) { };
	virtual ~TestProperty () { };

	virtual Property * clone () { return new TestProperty(*this); }
    virtual Property::Type& propertyType () { return c_TestType; };

};
Property::Type TestProperty::c_TestType = "TestProperty";

class TestBehavior : public Behavior {
public:
	typedef boost::weak_ptr<Property> PropertyPtr;
	PropertyPtr position;

	TestBehavior () { };
	virtual ~TestBehavior () { };

	virtual Behavior * clone () {
		return new TestBehavior ();
	};
	virtual bool initialize () { 
		if (owner) {
            position = owner->obtainProperty(std::string(TEST_PROPERTY_POSITION));
		}
		return true; 
	};
	virtual bool update () { return true; };
};

class fixture_factorytest {
public:
    //Entity entity;
	TestProperty propFactory;
	TestProperty * p1;
	TestBehavior behaviorFactory;
	TestBehavior * b1;

	fixture_factorytest() {
		p1 = 0L;
		b1 = 0L;
	};
	~fixture_factorytest() { 
        if (p1) delete p1;
        if (b1) delete b1;
    };
};

BOOST_FIXTURE_TEST_CASE(FactoryTest, fixture_factorytest) { 

	propFactory.x = 1;
	propFactory.y = 2;
	propFactory.z = 3;
    PropertyFactory::registerProperty(propFactory, std::string(TEST_PROPERTY_POSITION));

    p1 = (TestProperty *) PropertyFactory::createProperty (std::string(TEST_PROPERTY_POSITION));
	BOOST_CHECK (p1);
	BOOST_CHECK (p1->x == 1);
	BOOST_CHECK (p1->y == 2);
	BOOST_CHECK (p1->z == 3);

	//BehaviorFactory::registerBehavior(behaviorFactory, std::string("testbehavior"));
	//b1 = (TestBehavior*) BehaviorFactory::createBehavior(std::string("testbehavior"));
	//BOOST_CHECK (b1);

    PropertyFactory * factory = PropertyFactory::singleton();
    if (factory) delete factory;
}



//--------------------------------------------------------
//  ENTITY TEST
//--------------------------------------------------------

/*

struct fixture_entitytest {
	Universe entity;
	TestBehavior * b1;

	fixture_entitytest() {
	};
	~fixture_entitytest() { };

};

BOOST_FIXTURE_TEST_CASE(EntityTest, fixture_entitytest) {
	entity.addBehavior(std::string("testbehavior"));
	b1 = (TestBehavior *) entity.findBehavior(std::string("testbehavior"));
}

*/

//--------------------------------------------------------
//  OWNER TEST
//--------------------------------------------------------

/*

struct fixture_ownertest {
    EntityPtr universe;
    EntityPtr p1;
    EntityPtr p11;
    EntityPtr p12;
    EntityPtr anonymous;
    EntityPtr owned;

    fixture_ownertest() {
	};
	~fixture_ownertest() {
        //universe.reset ();
    };

};

BOOST_FIXTURE_TEST_CASE(OwnerTest, fixture_ownertest) {
    universe.reset (new Universe());
    BOOST_CHECK (universe->getName() == std::string("universe"));
    
    p1 = boost::make_shared<Entity>(universe, std::string("p1"));
    p11 = boost::make_shared<Entity>(universe, std::string("p11"));
    p12 = boost::make_shared<Entity>(universe, std::string("p12"));
    anonymous = boost::make_shared<Entity>(universe);

    BOOST_CHECK (p1->isOwner (universe));
    BOOST_CHECK (p11->isOwner (universe));
    BOOST_CHECK (p12->isOwner (universe));
    BOOST_CHECK (universe->getName() == std::string("universe"));
    BOOST_CHECK (p1->getName() == std::string("p1"));
    //BOOST_CHECK (p1->getOwner() == universe);
    BOOST_CHECK (anonymous->getName() == std::string("gn:1:1")); // we can predict since this is the first one
    
    p11->changeOwner(p1);
    p12->changeOwner(p1);

    BOOST_CHECK (p1->isOwner (universe));
    BOOST_CHECK (p11->isOwner (p1));
    BOOST_CHECK (p12->isOwner (p1));

    BOOST_CHECK (p1->findOwned(std::string("p11"), owned) == true);
    BOOST_CHECK (owned == p11);
    BOOST_CHECK (universe->findOwned(std::string("p11"), owned) == false);

    //BOOST_CHECK (p1->get
}
*/

BOOST_AUTO_TEST_SUITE_END()
